<?php

namespace App\Models;

use App\Support\upload;

/**
 * 图片模型
 * 负责图片的上传
 */
class Picture extends BaseModel
{
    protected $table = "picture";
    public $timestamps = false;

    protected $rules = [
        'name' => 'required',
        'path' => 'required',
        'url' => 'required',
        'md5' => 'required',
        'sha1' => 'required',
    ];

    protected $message = [
        'name.required' => '图片名称获取失败',
        'path.required' => '图片路径获取失败',
        'url.required' => '图片url获取失败',
        'md5.required' => '图片md5获取失败',
        'sha1.required' => '图片sha1获取失败',
    ];

    /**
     * 文件上传
     * @param  array $files 要上传的文件列表（通常是$_FILES数组）
     * @param  array $setting 文件上传配置
     * @param  string $driver 上传驱动名称
     * @param  array $config 上传驱动配置
     * @return array           文件上传成功后的信息
     */
    public function upload($files, $setting, $driver = 'Local', $config = null)
    {
        /* 上传文件 */
        $setting['callback'] = [$this, 'isFile'];
        $setting['removeTrash'] = [$this, 'removeTrash'];
        $uploadObj = new Upload($setting, $driver, $config);
        $info = $uploadObj->upload($files);
        if ($info) { //文件上传成功，记录文件信息
            foreach ($info as $key => &$value) {
                /* 已经存在文件记录 */
                if (isset($value['id']) && is_numeric($value['id'])) {
                    continue;
                }
                /* 记录文件信息 */
                $value['path'] = substr($setting['rootPath'], 1) . $value['savepath'] . $value['savename'];    //在模板里的url路径
                if ($this->add($value)) {
                    $value['id'] = $this->id;
                    $value['url'] = $this->url;
                } else {
                    //TODO: 文件上传成功，但是记录文件信息失败，需记录日志
                    unset($info[$key]);
                }
            }
            return $info; //文件上传成功
        } else {
            $this->error = $uploadObj->getError();
            return false;
        }
    }

    public function add($img)
    {
        if (!is_login()) {
            $this->error = '请登录后操作!';
            return false;
        }
        if (!request('shop_id')) {
            $this->error = '请选择店铺后才能上传!';
            return false;
        }
        $data['admin_id'] = is_login();
        $data['shop_id'] = intval(trim(request('shop_id')));
        $data['name'] = $img['savename'];
        $data['path'] = $img['path'];
        $data['url'] = config('upload.PICTURE_UPLOAD.rootPath').request('shop_id').'/'.$img['savename'];
        $data['md5'] = $img['md5'];
        $data['sha1'] = $img['sha1'];
        $data['status'] = 1;
        $data['addtime'] = time();
        if (!$this->_validate($data)) {
            return false;
        }
        $res = $this->_save($data);
        if ($res) {
//            $id = isset($data['id']) ? $data['id'] : $this->id;
            //记录行为
//            action_log('update_shop', 'shop', $id);
        }
        return $res;
    }

    /**
     * 下载指定文件
     * @param  number $root 文件存储根目录
     * @param  integer $id 文件ID
     * @param  string $args 回调函数参数
     * @return boolean       false-下载失败，否则输出下载文件
     */
    public function download($root, $id, $callback = null, $args = null)
    {
        /* 获取下载文件信息 */
        $file = $this->_getOneById($id)->toArray();
        if (!$file) {
            $this->error = '不存在该文件！';
            return false;
        }

        /* 下载文件 */
        switch ($file['location']) {
            case 0: //下载本地文件
                $file['rootpath'] = $root;
                return $this->downLocalFile($file, $callback, $args);
            case 1: //TODO: 下载远程FTP文件
                break;
            default:
                $this->error = '不支持的文件存储类型！';
                return false;

        }

    }

    /**
     * 检测当前上传的文件是否已经存在
     * @param  array $file 文件上传数组
     * @return boolean       文件信息， false - 不存在该文件
     */
    public function isFile($file)
    {
        if (empty($file['md5'])) {
            throw new \Exception('缺少参数:md5');
        }
        /* 查找文件 */
        $where = ['md5' => $file['md5'], 'sha1' => $file['sha1']];
        return $this->_getOne($where)->toArray();
    }

    /**
     * 下载本地文件
     * @param  array $file 文件信息数组
     * @param  callable $callback 下载回调函数，一般用于增加下载次数
     * @param  string $args 回调函数参数
     * @return boolean            下载失败返回false
     */
    private function downLocalFile($file, $callback = null, $args = null)
    {
        if (is_file($file['rootpath'] . $file['savepath'] . $file['savename'])) {
            /* 调用回调函数新增下载数 */
            is_callable($callback) && call_user_func($callback, $args);

            /* 执行下载 */ //TODO: 大文件断点续传
            header("Content-Description: File Transfer");
            header('Content-type: ' . $file['type']);
            header('Content-Length:' . $file['size']);
            if (preg_match('/MSIE/', $_SERVER['HTTP_USER_AGENT'])) { //for IE
                header('Content-Disposition: attachment; filename="' . rawurlencode($file['name']) . '"');
            } else {
                header('Content-Disposition: attachment; filename="' . $file['name'] . '"');
            }
            readfile($file['rootpath'] . $file['savepath'] . $file['savename']);
            exit;
        } else {
            $this->error = '文件已被删除！';
            return false;
        }
    }

    /**
     * 清除数据库存在但本地不存在的数据
     * @param $data
     */
    public function removeTrash($data)
    {
        $this->_del(['id' => $data['id']]);
    }

}